PreviousNextTracker indexSee it online !

(128/185) 294 - XML: Wrap selection in a tag

Hi there,

I primarily work with HTML and XML. I find jEdit to be an amazing tool, in particular how sidekick parses and displays the markup language.

One feature that I would dearly like, is a way for me to:

i) Wrap selected lines with tags
ii) Wrap a selection with tag

1) Wrap selection with an arbitrary tag

Often time, I'm required to take multiple lines and wrap them with an arbitrary tag. Right now, I make use of beanshell macros to do this, but they are hardcoded to specific tags (like <li> or <p>). I would like to do this without having to type into a dialog box.

See image 01_jetbrains_IDEA_wrap_in_tag.png

2)



Submitted taitoh - 2012-04-27 19:01:52 Assigned kerik-sf
Priority 5 Labels XML
Status open Group None
Resolution None

Comments

2012-04-27 19:01:53
taitoh

Image of Jetbrains IDEA wrapping a selection with an arbitrary tag

01_jetbrains_IDEA_wrap_in_tag.png (97.2Kio)

2012-04-27 19:07:00
taitoh

Oops...

2) I would like to have the option to do this across multiple lines. This is great for making individual paragraphs or list elements. I have macros that do it, but some editors on OS X (like Textmate, espresso) do this out of the box.

See image 02_Wrap_selected_lines_in_tag.png

Thanks,

Tai

2012-04-27 19:07:40
taitoh

Image of Espresso with Wrap selected lines in tag.

02_Wrap_selected_lines_in_tag.png (129.4Kio)

2012-04-27 19:23:39
daleanson

- **labels**: 871558 -->

2012-04-27 19:23:39
daleanson

Looks like a nice feature for the XML plugin.

2012-04-27 19:37:42
jarekczek

- **labels**: --> XML
- **summary**: Wrap selection in a tag --> XML: Wrap selection in a tag

2012-04-27 19:38:17
jarekczek

- **assigned_to**: nobody --> kerik-sf

2012-04-27 20:27:24
taitoh

Thanks Dale,

I'd love to see it implemented.

-T

2013-07-31 19:25:11
ezust

- **priority**: 5 --> 7

2013-07-31 19:25:11
ezust

+1 to that\!\!

2013-07-31 20:13:24
sjakob

Have you tried the XInsert plugin? Not sure about arbitrary tags, but it looks like it might not be too difficult to create your own custom tag libraries.

2013-08-01 04:38:19
ezust

Actually, now that you mention it, this might be a templates or supertemplates or xinsert feature rather than something that needs to be added to XML plugin, but Ia m not familiar enough with those other plugins to say for sure.

In my earlier comment, when I said +1 to that, I thought this request was for reformatting words (as in word wrap) for the contents between a tag (instead of using the traditional paragraph separation criteria that jedit's built in reformat paragraph uses) but after looking at the images you attached, I realize your request is not about word wrap, but "tag wrapping".

2013-08-01 04:38:28
ezust

- **priority**: 7 --> 5

2017-10-31 23:23:39.425000
ngc

Does this Macro help? (Small bug fixed 2017-11-02)





os=textArea.getSelection();
om=textArea.isMultipleSelectionEnabled();
if (! om) {
textArea.toggleMultipleSelectionEnabled();
}

int[] sl= new int[os.length];
int[] el= new int[os.length];
String[] in= new String[os.length];
boolean appendLine= false;
for (i=os.length; i-->0; ) {
sl[i]= os[i].getStartLine();
el[i]= os[i].getEndLine();
if ( textArea.getLineStartOffset(el[i]) == os[i].getEnd() ) {
--el[i];
}
appendLine= el[i]+1 == textArea.getLineCount();
in[i]= textArea.getLineText(sl[i]).replaceFirst("\\S.*$","");
}

textArea.shiftIndentRight();
textArea.selectNone();

if ( appendLine ) {
textArea.setCaretPosition(textArea.getBufferLength());
textArea.setSelectedText("\n");
}

la= 0;
for (i=0; i<os.length; ++i) {
textArea.setCaretPosition(textArea.getLineStartOffset(sl[i]+la));
sl[i]= textArea.getCaretPosition()+in[i].length()+1;
textArea.setSelectedText(in[i]+"<tag>\n");
++la;
textArea.setCaretPosition(textArea.getLineStartOffset(el[i]+1+la));
el[i]= textArea.getCaretPosition()+in[i].length()+2;
textArea.setSelectedText(in[i]+"</tag>\n");
++la;
}

for (i=os.length; i-->0;) {
textArea.addToSelection(new Selection.Range( sl[i], sl[i]+3 ));
textArea.addToSelection(new Selection.Range( el[i], el[i]+3 ));
}

Just select whatever block(s) you want to surround with a tag, call the Macro and start typing the tag.

Example: https://youtu.be/H5FluV_J11o

Example with the bugfix: https://youtu.be/WflpyHzeYvo

2017-11-02 11:01:58.546000
ngc

One more iteration without a video this time.

This version will put the tags on the same line the text is in, if the selection is just a single line.



os=textArea.getSelection();
om=textArea.isMultipleSelectionEnabled();
if (! om) {
textArea.toggleMultipleSelectionEnabled();
}

int[] sl= new int[os.length];
int[] el= new int[os.length];
boolean[] ol= new boolean[os.length];
String[] in= new String[os.length];
boolean appendLine= false;
boolean oneLine= false;
for (i=os.length; i-->0; ) {
sl[i]= os[i].getStartLine();
el[i]= os[i].getEndLine();
ol[i]= oneLine= sl[i] == el[i];
if ( ! oneLine && textArea.getLineStartOffset(el[i]) == os[i].getEnd() ) {
--el[i];
}
appendLine= !oneLine && el[i]+1 == textArea.getLineCount();
in[i]= textArea.getLineText(sl[i]).replaceFirst("\\S.*$","");
if (oneLine) {
textArea.removeFromSelection( os[i] );
}
}

textArea.shiftIndentRight();
textArea.selectNone();

if ( appendLine ) {
textArea.setCaretPosition(textArea.getBufferLength());
textArea.setSelectedText("\n");
}

la= 0;
for (i=0; i<os.length; ++i) {
textArea.setCaretPosition(textArea.getLineStartOffset(sl[i]+la));
if (ol[i]) {
textArea.goToStartOfWhiteSpace(false);
sl[i]= textArea.getCaretPosition()+1;
textArea.setSelectedText("<tag>");
textArea.goToEndOfWhiteSpace(false);
el[i]= textArea.getCaretPosition()+2;
textArea.setSelectedText("</tag>");
}
else {
sl[i]= textArea.getCaretPosition()+in[i].length()+1;
textArea.setSelectedText(in[i]+"<tag>\n");
++la;
textArea.setCaretPosition(textArea.getLineStartOffset(el[i]+1+la));
el[i]= textArea.getCaretPosition()+in[i].length()+2;
textArea.setSelectedText(in[i]+"</tag>\n");
++la;
}
}

for (i=os.length; i-->0;) {
textArea.addToSelection(new Selection.Range( sl[i], sl[i]+3 ));
textArea.addToSelection(new Selection.Range( el[i], el[i]+3 ));
}

if (! om) {
textArea.toggleMultipleSelectionEnabled();
}

2017-11-02 20:16:35.269000
tsourick

This would be a super cool feature!

Unfortunately the latter macro has some issues:
- adds unecessary tab before selection
- does not turn off multiple selection after
- seems like there is no way to just enclose single word on a line, encloses the whole text
- has no way to "finish" the process

2017-11-02 21:54:32.802000
ngc

> - adds unecessary tab before selection

I do not think the tab is unneccessary. The content should be indented a level more than the tag - but this is my personal preference. Remove the shiftIndentRight().

> - does not turn off multiple selection after

I fixed the multiple selection "issue". If it was off before it will be off after the macro call. See the last 3 lines of the macro [ if ( ! om ) … ]

> - seems like there is no way to just enclose single word on a line, encloses the whole text

It is. If you have multiple selections on and do not select a block but single lines (even a character per line is sufficient, then just those lines will be surrounded by tags. But yes - not single word. Always the whole line at least.

> - has no way to "finish" the process

Press Esc when done.

2017-11-04 19:47:30.190000
tsourick

Now I understand your use case.
You must be selecting a block of text, multiline, and I agree, it is good to indent the inner content.
While I was telling about a single line, which should not be indented, because it is already indented 99% of the time. May be you could improve it even further, checking if the text selected is on the single line or not and apply indentation accrodingly.

Ok.

Would be nice to have this too.

Works. Would be great to finish on Enter also if possible.

Thank you!

2017-11-06 07:41:46.753000
ngc

I already checkeked whether the selection is on just one line.

But there was a bug in the macro indenting the current line when all selections were just one-liners.

Fixed now with nbelow code:



os=textArea.getSelection();
om=textArea.isMultipleSelectionEnabled();
if (! om) {
textArea.toggleMultipleSelectionEnabled();
}

int[] sl= new int[os.length];
int[] el= new int[os.length];
boolean[] ol= new boolean[os.length];
String[] in= new String[os.length];
boolean appendLine= false;
boolean oneLine= false;
int remainingSelections= os.length;
for (i=os.length; i-->0; ) {
sl[i]= os[i].getStartLine();
el[i]= os[i].getEndLine();
ol[i]= oneLine= sl[i] == el[i];
if ( ! oneLine && textArea.getLineStartOffset(el[i]) == os[i].getEnd() ) {
--el[i];
}
appendLine= !oneLine && el[i]+1 == textArea.getLineCount();
in[i]= textArea.getLineText(sl[i]).replaceFirst("\\S.*$","");
if (oneLine) {
textArea.removeFromSelection( os[i] );
--remainingSelections;
}
}

if (remainingSelections > 0) {
textArea.shiftIndentRight();
}
textArea.selectNone();

if ( appendLine ) {
textArea.setCaretPosition(textArea.getBufferLength());
textArea.setSelectedText("\n");
}

la= 0;
for (i=0; i<os.length; ++i) {
textArea.setCaretPosition(textArea.getLineStartOffset(sl[i]+la));
if (ol[i]) {
textArea.goToStartOfWhiteSpace(false);
sl[i]= textArea.getCaretPosition()+1;
textArea.setSelectedText("<tag>");
textArea.goToEndOfWhiteSpace(false);
el[i]= textArea.getCaretPosition()+2;
textArea.setSelectedText("</tag>");
}
else {
sl[i]= textArea.getCaretPosition()+in[i].length()+1;
textArea.setSelectedText(in[i]+"<tag>\n");
++la;
textArea.setCaretPosition(textArea.getLineStartOffset(el[i]+1+la));
el[i]= textArea.getCaretPosition()+in[i].length()+2;
textArea.setSelectedText(in[i]+"</tag>\n");
++la;
}
}

for (i=os.length; i-->0;) {
textArea.addToSelection(new Selection.Range( sl[i], sl[i]+3 ));
textArea.addToSelection(new Selection.Range( el[i], el[i]+3 ));
}

if (! om) {
textArea.toggleMultipleSelectionEnabled();
}

2017-11-07 00:32:16.558000
tsourick

Yes, now it respects nubmer of lines.

I've noticed another issue, the backspace does not work at all while typing the tag name.

Probably it goes beyond the macro. Even this really helps I believe.